package device

import (
	"context"
	"encoding/json"
	"strconv"
	"strings"

	"gitee.com/wenchangshou/simple-admin-pancakebot-rpc/ent/combo"
	types2 "gitee.com/wenchangshou/simple-admin-pancakebot-rpc/ent/types"
	"gitee.com/wenchangshou/simple-admin-pancakebot-rpc/internal/svc"
	"gitee.com/wenchangshou/simple-admin-pancakebot-rpc/internal/utils/dberrorhandler"
	"gitee.com/wenchangshou/simple-admin-pancakebot-rpc/types/pancakebot"
	"github.com/suyuan32/simple-admin-common/msg/errormsg"
	"github.com/twpayne/go-geom"
	"github.com/twpayne/go-geom/encoding/geojson"
	"github.com/zeromicro/go-zero/core/errorx"
	"github.com/zeromicro/go-zero/core/logx"
)

type CreateDeviceLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewCreateDeviceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateDeviceLogic {
	return &CreateDeviceLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

// CreateDevice Device management
func (l *CreateDeviceLogic) CreateDevice(in *pancakebot.DeviceInfo) (*pancakebot.BaseIDResp, error) {
	exists, err := l.svcCtx.DB.Combo.Query().Where(combo.NameEqualFold(*in.DeviceName)).Exist(l.ctx)
	if err != nil {
		return nil, dberrorhandler.DefaultEntError(l.Logger, err, in)
	}
	if exists {
		return nil, errorx.NewInvalidArgumentError("device.nameExist")
	}
	query := l.svcCtx.DB.Device.Create().
		SetDeviceName(*in.DeviceName).
		SetDeviceNo(int(*in.DeviceNo)).
		SetDeviceStatus(int(*in.DeviceStatus)).
		SetType(int(*in.Type)).
		SetNotNilAddress(in.Address)
	if in.Location != nil && (*in.Location) != "" {

		coords := strings.Split(*in.Location, ",")
		if len(coords) != 2 {
			return nil, errorx.NewInvalidArgumentError("location format should be 'lng,lat'")
		}

		lng, err := strconv.ParseFloat(strings.TrimSpace(coords[0]), 64)
		if err != nil {
			return nil, errorx.NewInvalidArgumentError("invalid longitude: " + coords[0])
		}

		lat, err := strconv.ParseFloat(strings.TrimSpace(coords[1]), 64)
		if err != nil {
			return nil, errorx.NewInvalidArgumentError("invalid latitude: " + coords[1])
		}

		// 使用 go-geom 创建点
		point := geom.NewPoint(geom.XY).MustSetCoords(geom.Coord{lng, lat})

		// 转换为 GeoJSON
		geoJsonBytes, err := geojson.Marshal(point)
		if err != nil {
			return nil, errorx.NewInvalidArgumentError("failed to create GeoJSON")
		}

		var geoJsonGeometry geojson.Geometry
		if err := json.Unmarshal(geoJsonBytes, &geoJsonGeometry); err != nil {
			return nil, errorx.NewInvalidArgumentError("failed to parse GeoJSON geometry")
		}

		geoJsonObj := &types2.GeoJson{
			Geometry: &geoJsonGeometry,
		}
		query.SetLocation(geoJsonObj)
	}
	result, err := query.Save(l.ctx)

	if err != nil {
		return nil, dberrorhandler.DefaultEntError(l.Logger, err, in)
	}

	return &pancakebot.BaseIDResp{Id: result.ID, Msg: errormsg.CreateSuccess}, nil
}
